package com.ocp.macro.utils;


import com.ocp.macro.entity.Payload;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.TimeoutUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
public class JwtUtil {
    private final static String USER_INFO_KEY = "info";

    /**
     * 生成一个token
     * @param request HttpServletRequest
     * @param info 进行封装的信息
     * @param timeout 过期时间，单位秒，-1表示永不过期
     * @param unit 时间类型
     * @return 返回一个token，和一个用于解密的密钥
     */
    public static String[] createToken(HttpServletRequest request, Object info, long timeout, TimeUnit unit){
        JwtBuilder builder = Jwts.builder();
        if (timeout != -1){
            long rawTimeout = TimeoutUtils.toMillis(timeout, unit);
            builder.setExpiration(new Date(System.currentTimeMillis() +rawTimeout));
        }

        // 将用户的ip+浏览器信息+系统信息作为密钥
        String privateKey = getPrivateKey(request);
        String[] token = new String[2];
        token[0] = privateKey;
        token[1] = builder.setIssuedAt(new Date())
                .setId(createJTI())
                .claim(USER_INFO_KEY, GsonUtils.toJson(info))
                .signWith(SignatureAlgorithm.HS256, privateKey).compact();
        return token;
    }


    /**
     * 解析token信息
     * @param privateKey 密钥
     * @param token token
     * @param userType 用户数据类型
     * @return 返回信息
     */
    public static <T> Payload<T> getInfoFromToken(String privateKey, String token, Class<T> userType) {
        Claims body = null;
        try{
            body = Jwts.parser().setSigningKey(privateKey)
                    .parseClaimsJws(token).getBody();
        }catch (Exception e){
            log.error("解析token出错：{}",e.toString());
            return null;
        }
        Payload<T> claims = new Payload<>();
        claims.setId(body.getId());
        claims.setUserInfo(GsonUtils.toBean(body.get(USER_INFO_KEY).toString(), userType));
        claims.setExpiration(body.getExpiration());
        return claims;
    }

    public static String getPrivateKey(HttpServletRequest request){
        return InfoCountUtils.getIp(request)+InfoCountUtils.getBrowser(request)+InfoCountUtils.getSysInfo(request);
    }

    private static String createJTI() {
        return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
    }
}
